/**
    签名
        可选画笔的类型（画笔，橡皮）
        可选画笔的粗细
        可选画笔的颜色

        props
            title[string = '签名板'] 弹窗的标题
            show.sync[boolean = false] 组件是否显示
            defaultLineWidthIndex[number = 0] 画笔的粗细选项数组的默认下表
            defaultStrokeStyleIndex[number = 0] 画笔的颜色选项数组的默认下表
        
        emit
            save(str) 点保存触发
                str 签名的base64数据

        slot
            beforeCanvas 签名区域前面的插槽

 */

<template>
    <el-dialog class="v-sign"
               :title="title"
               width="840px"
               :visible.sync="visible"
               :modal-append-to-body="false"
               :close-on-click-modal="false"
               :close-on-press-escape="false"
               @closed="fnClosed">
        <slot name="beforeCanvas"></slot>
        <div class="canvas-div">
            <canvas width="800"
                    height="400"
                    ref="canvas"
                    :class="{ erase: brushType === 'erase' }"
                    @mousedown.left="fnMousedown"
                    @mouseup.left="fnMouseup"
                    @mousemove.left="fnMousemove">你的浏览器不支持 canvas，请更换浏览器</canvas>
        </div>
        <el-form class="position-div"
                 label-width="80px"
                 label-position="left">
            <el-form-item label="画笔类型">
                <el-radio-group v-model="brushType">
                    <el-radio label="brush">画笔</el-radio>
                    <el-radio label="erase">橡皮</el-radio>
                </el-radio-group>
            </el-form-item>

            <el-form-item label="画笔粗细">
                <el-radio-group v-model="lineWidth"
                                @change="fnLineWidthChange">
                    <template v-for="item in radioLineWidth">
                        <el-radio :key="item"
                                  :label="item">{{ item }}px</el-radio>
                    </template>
                </el-radio-group>
            </el-form-item>

            <el-form-item label="画笔颜色">
                <div class="color-div">
                    <template v-for="(item, index) in radioStrokeStyle">
                        <span :key="index"
                              @click.stop="fnStrokeStyleChange(item)"
                              :class="{ active: strokeStyle === item }">
                            <i :style="`background: ${item}`"></i>
                        </span>
                    </template>
                </div>
            </el-form-item>
        </el-form>

        <div slot="footer">
            <el-button @click="fnClosed()">关 闭</el-button>
            <el-popconfirm class="el-popconfirm"
                           title="是否确定清空画板？"
                           @confirm="fnClearCanvas">
                <el-button slot="reference">清 空</el-button>
            </el-popconfirm>
            <el-button type="primary"
                       @click="fnSave()">保 存</el-button>
        </div>
    </el-dialog>
</template>

<script>
export default {
    props: {
        title: {
            type: String,
            default: "签名板",
        },
        show: {
            type: Boolean,
            default: false,
        },
        defaultLineWidthIndex: {
            type: Number,
            default: 0,
        },
        defaultStrokeStyleIndex: {
            type: Number,
            default: 0,
        },
    },

    data () {
        return {
            // el-dialog的显示
            visible: false,
            // 是否正在签名
            isSign: false,
            // 鼠标按下的位置
            mousedownOffset: null,
            // 鼠标移动中时的位置
            mousemoveOffset: null,
            // canvas实例
            canvas: null,
            // canvas2D实例
            ctx: null,
            // 画笔的粗细
            lineWidth: null,
            // 画笔粗细的取值
            radioLineWidth: [1, 3, 5, 7],
            // 画笔的颜色
            strokeStyle: null,
            // 画笔颜色的取值
            radioStrokeStyle: [
                "#000000",
                "#ff0000",
                "#ff8000",
                "#ffff00",
                "#40ff00",
                "#00ffff",
                "#5673FF",
                "#ff00ff",
            ],
            // 画笔的类型
            brushType: "brush",
        };
    },

    methods: {
        // 关闭完成触发
        fnClosed () {
            this.visible = false;
            this.$emit("update:show", false);
        },
        // 鼠标按下
        fnMousedown (evt) {
            this.isSign = true;

            if (this.brushType === "brush") {
                // 画笔
                this.mousedownOffset = {
                    offsetX: evt.offsetX,
                    offsetY: evt.offsetY,
                };
            } else {
                // 橡皮
                this.fnErase(evt.offsetX, evt.offsetY);
            }
        },
        // 鼠标松开
        fnMouseup (evt) {
            this.isSign = false;

            if (this.brushType === "brush") {
                // 画笔
                if (this.mousemoveOffset) {
                    this.$nextTick(() => {
                        this.fnCreateLine(this.mousemoveOffset, {
                            offsetX: evt.offsetX,
                            offsetY: evt.offsetY,
                        });

                        this.mousemoveOffset = null;
                    });
                } else {
                    this.$nextTick(() => {
                        this.fnCreateLine(this.mousedownOffset, {
                            offsetX: evt.offsetX,
                            offsetY: evt.offsetY,
                        });
                    });
                }
            }
        },
        // 鼠标移动
        fnMousemove (evt) {
            if (this.isSign) {
                if (this.brushType === "brush") {
                    // 画笔
                    if (this.mousemoveOffset) {
                        this.fnCreateLine(this.mousemoveOffset, {
                            offsetX: evt.offsetX,
                            offsetY: evt.offsetY,
                        });
                    } else {
                        this.fnCreateLine(this.mousedownOffset, {
                            offsetX: evt.offsetX,
                            offsetY: evt.offsetY,
                        });
                    }

                    this.mousemoveOffset = {
                        offsetX: evt.offsetX,
                        offsetY: evt.offsetY,
                    };
                } else {
                    // 橡皮
                    this.fnErase(evt.offsetX, evt.offsetY);
                }
            }
        },
        // 创建线
        fnCreateLine (path1, path2) {
            this.ctx.beginPath();
            this.ctx.moveTo(path1.offsetX, path1.offsetY);
            this.ctx.lineTo(path2.offsetX, path2.offsetY);
            this.ctx.stroke();
        },
        // 改变画笔的粗细
        fnLineWidthChange (item) {
            this.lineWidth = item;
            this.ctx.lineWidth = item;
        },
        // 改变画笔的颜色
        fnStrokeStyleChange (item) {
            this.strokeStyle = item;
            this.ctx.strokeStyle = item;
        },
        // 清空签名
        fnClearCanvas () {
            this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
        },
        // 橡皮檫
        fnErase (x, y) {
            this.ctx.beginPath();
            this.ctx.fillStyle = "#f1f1f1";
            this.ctx.arc(x, y, 8, 0, Math.PI * 2, true);
            this.ctx.fill();
        },
        // 保存
        fnSave () {
            let base64 = this.canvas.toDataURL();
            console.log(base64);
            this.$emit("save", base64);
        },
    },

    watch: {
        show: function (val) {
            this.visible = val

            if (val === true) {
                this.$nextTick(() => {
                    if (!this.canvas) {
                        // 初始化canvas的一些配置
                        this.canvas = this.$refs.canvas
                        this.ctx = this.canvas?.getContext("2d")
                        if (!this.ctx) return

                        this.lineWidth = this.radioLineWidth[this.defaultLineWidthIndex]
                        this.ctx.lineWidth = this.lineWidth
                        this.ctx.lineCap = "round"
                        this.strokeStyle = this.radioStrokeStyle[this.defaultStrokeStyleIndex]
                        this.ctx.strokeStyle = this.strokeStyle
                    }
                });
            }
        },
    },
};
</script>

<style scoped lang="scss">
.canvas-div {
    canvas {
        background: #f1f1f1;
        cursor: url("./imgs/brush.jpg"), auto;

        &.erase {
            cursor: url("./imgs/erase.jpg"), auto;
        }
    }
}

.position-div {
    padding-top: 10px;
}

.color-div {
    display: flex;

    span {
        flex: 1;
        height: 32px;
        cursor: pointer;
        padding: 4px 6px;
        display: flex;

        &.active {
            border: 2px solid $mc;
        }

        i {
            flex: 1;
        }
    }
}
</style>